#include <iostream>
#include <string>
#include <memory>

class fruit
{
public:
    virtual void print_name() = 0; //纯虚函数

private:
    std::string _name;
};

class apple:public fruit
{
public:
    void print_name() override {std::cout << "苹果" << std::endl;}
};

class banana:public fruit
{
public:
    void print_name() override {std::cout << "香蕉" << std::endl;}
};

// // 简单工厂模式
// class fruit_factory
// {
// public:
//     static std::shared_ptr<fruit> creat(const std::string& name)
//     {
//         if(name == "苹果")
//             return std::make_shared<apple>();
//         else if(name == "香蕉")
//             return std::make_shared<banana>();
//     }
// };

// // 工厂方法模式
// class fruit_factory
// {
// public:
//     virtual std::shared_ptr<fruit> creat() = 0;
// };

// class apple_factory : public fruit_factory
// {
// public:
//     std::shared_ptr<fruit> creat() override
//     {
//         return std::make_shared<apple>();
//     }
// };

// class banana_factory : public fruit_factory
// {
// public:
//     std::shared_ptr<fruit> creat() override
//     {
//         return std::make_shared<banana>();
//     }
// };

class animal
{
public:
    virtual void print_name() = 0;
};

class dog : public animal
{
public:
    void print_name() override
    {
        std::cout << "狗" << std::endl;
    }
};

class cat : public animal
{
public:
    void print_name() override
    {
        std::cout << "猫" << std::endl;
    }
};

// 抽象工厂模式
class factory
{
public:
    virtual std::shared_ptr<fruit> get_fruit(const std::string& name) = 0;
    virtual std::shared_ptr<animal> get_animal(const std::string& name) = 0;
};

class fruit_factory : public factory
{
public:
    virtual std::shared_ptr<fruit> get_fruit(const std::string& name)
    {
        if(name == "苹果")
            return std::make_shared<apple>();
        else if(name == "香蕉")
            return std::make_shared<banana>();
    }

    virtual std::shared_ptr<animal> get_animal(const std::string& name)
    {
        // 须使用shared_ptr
        return std::shared_ptr<animal>();
    }
};

class animal_factory : public factory
{
public:
    virtual std::shared_ptr<fruit> get_fruit(const std::string& name)
    {
        // 须使用shared_ptr
        return std::shared_ptr<fruit>();
    }

    virtual std::shared_ptr<animal> get_animal(const std::string& name)
    {
        if(name == "狗")
            return std::make_shared<dog>();
        else if(name == "猫")
            return std::make_shared<cat>();
    }
};

class factory_producer
{
public:
    static std::shared_ptr<factory> get_factory(const std::string& str)
    {
        if(str == "水果")
            return std::make_shared<fruit_factory>();
        else if(str == "动物")
            return std::make_shared<animal_factory>();
    }
};


int main()
{
    // // 简单工厂模式
    // std::shared_ptr<fruit> fruit = fruit_factory::creat("苹果");
    // fruit->print_name();
    // fruit = fruit_factory::creat("香蕉");
    // fruit->print_name();

    // // 工厂方法模式
    // std::shared_ptr<fruit_factory> ff(new apple_factory());
    // std::shared_ptr<fruit> fruit(ff->creat());
    // fruit->print_name();
    // ff.reset(new banana_factory());
    // fruit = ff->creat();
    // fruit->print_name();

    // 抽象工厂模式
    std::shared_ptr<factory> ff = factory_producer::get_factory("水果");
    std::shared_ptr<fruit> f = ff->get_fruit("香蕉");
    f->print_name();
    f = ff->get_fruit("苹果");
    f->print_name();

    std::shared_ptr<factory> ff2 = factory_producer::get_factory("动物");
    std::shared_ptr<animal> f2 = ff2->get_animal("狗");
    f2->print_name();
    f2 = ff2->get_animal("猫");
    f2->print_name();

    return 0;
}